﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace 服务端双缓冲队列
{
    public class 线程安全LIst测试
    {

        public static 线程安全LIst测试 _instance;

        public static 线程安全LIst测试 Create()
        {
            return _instance ?? (_instance = new 线程安全LIst测试());
        }

        /// <summary>
        /// 记录数据
        /// </summary>
        public long RecordNum = 0;

        /// <summary>
        /// 最大循环次数
        /// </summary>
        public long MaxRun = 10;

        private readonly List<string> _waitExecData;

        private readonly List<string> _waitExecData001;

        public bool IsRuning { get; set; }

        private int _queueFlag;
        private int _threshold = 100;

        private 线程安全LIst测试()
        {
            IsRuning = true;
            if (_waitExecData == null)
                _waitExecData = new List<string>();
            if (_waitExecData001 == null)
                _waitExecData001 = new List<string>();
        }

        public void Init(int threadCount, int threshold)
        {
            for (var i = 0; i < threadCount; i++)
            {
                //Task.Factory.StartNew(DoWork);
            }
            _threshold = threshold;
        }

        public void DoWork()
        {
            while (IsRuning)
            {
                try
                {
                    Execute();
                }
                catch
                {

                }
            }
        }

        private void Execute()
        {
            string val = string.Empty;

            switch (_queueFlag)
            {
                case 0:
                    lock (_waitExecData)
                    {
                        if (_waitExecData.Count > 0)
                        {
                            if (_waitExecData.Count > _threshold)
                            {
                                Interlocked.Exchange(ref _queueFlag, 2);
                            }

                            val = _waitExecData[0];
                            _waitExecData.RemoveAt(0);

                        }
                    }
                    break;
                case 1:
                    if (_waitExecData001.Count > 0)
                    {
                        val = _waitExecData001[0];
                        _waitExecData001.RemoveAt(0);
                    }
                    else
                    {
                        Interlocked.Exchange(ref _queueFlag, 2);
                    }
                    break;
                case 2:
                    if (_waitExecData.Count > 0)
                    {
                        val = _waitExecData[0];
                        _waitExecData.RemoveAt(0);
                    }
                    else
                    {
                        Interlocked.Exchange(ref _queueFlag, 1);
                    }
                    break;
            }

            ///
            if (string.IsNullOrEmpty(val))
            {
                if (RecordNum > MaxRun - MaxRun / 100)
                {
                    IsRuning = false;
                }
                return;
            }

            Interlocked.Add(ref  RecordNum, 1);
            if (RecordNum >= MaxRun)
            {
                IsRuning = false;
            }


            //Console.Write(val);
        }


        public void Push(string message)
        {
            switch (_queueFlag)
            {
                case 0: //特征，加锁
                    lock (_waitExecData)
                    {
                        _waitExecData.Add(message);
                    }
                    break;
                case 1: //特征，不加锁
                    _waitExecData.Add(message);
                    break;
                case 2: //特征，不加锁
                    _waitExecData001.Add(message);
                    break;
            }
        }
    }
}
